﻿using BackupContracts.Sql;
using Silverlight.BackupServiceReference;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Silverlight.DataSources
{
    public class BackupServiceDataSource
    {
        private BackupServiceDataSource()
        {
           //ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => 
           // {
           //     return cert.Subject.Contains("localhost");
           // };        
        }

        private static BackupServiceDataSource _Instance;
        public static BackupServiceDataSource Instance
        {
            get 
            {
                if (_Instance == null)
                { 
                    _Instance = new BackupServiceDataSource();
                }
                return _Instance;
            }
        }

        public async Task<bool> AuthenticateAsync() 
        {
            try
            {
                var backupService = CreateBackupServiceClient();

                return await Task.Factory.FromAsync<bool>(backupService.BeginCheckCredentials, backupService.EndCheckCredentials, null);
            }
            catch (Exception e) 
            {
                LogException("Authenticate", e);
            }
            return false;
        }

        private IBackupService CreateBackupServiceClient()
        {
            var backupServiceClient = new BackupServiceClient();
            backupServiceClient.Endpoint.Address = 
                new System.ServiceModel.EndpointAddress(
                    Application.Current.Host.Source.AbsoluteUri.Substring(0, Application.Current.Host.Source.AbsoluteUri.Length - Application.Current.Host.Source.AbsolutePath.Length) + 
                    "/BackupService.svc/BackupService.svc");
            backupServiceClient.ClientCredentials.UserName.UserName = User;
            backupServiceClient.ClientCredentials.UserName.Password = Password;
            var backupService = (IBackupService)backupServiceClient;
            return backupService;
        }

        private void LogException(string p, Exception e)
        {

        }

        public string User { get; set; }

        public string Password { get; set; }

        public async Task<ObservableCollection<SqlDatabase>> ListAllDatabasesAsync(string serverName)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                return await Task.Factory.FromAsync<string, ObservableCollection<SqlDatabase>>(backupService.BeginListDatabases, backupService.EndListDatabases, serverName, null);
            }
            catch (Exception e)
            {
                LogException("ListSqlDatabases", e);
            }
            return null;
        }

        public async Task<ObservableCollection<SqlDatabaseBackup>> ListAllDatabaseBackupsAsync(string serverName, string databaseName)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                return await Task.Factory.FromAsync<string, string, ObservableCollection<SqlDatabaseBackup>>(backupService.BeginListDatabaseBackups, backupService.EndListDatabaseBackups, serverName, databaseName,  null);
            }
            catch (Exception e)
            {
                LogException("ListDatabaseBackups", e);
            }
            return null;
        }

        public async Task<string> GetPublicBlobUrl(string url)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                return await Task.Factory.FromAsync<string, string>(backupService.BeginGetPublicBlobUrl, backupService.EndGetPublicBlobUrl, url, null);
            }
            catch (Exception e)
            {
                LogException("GetPublicBlobUrl", e);
            }
            return null;
        }

        public async Task<ObservableCollection<SqlDatabaseBackupLog>> ListAllDatabaseBackupLogsAsync(string serverName, string databaseName, string backupId)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                return await Task.Factory.FromAsync<string, string, string, ObservableCollection<SqlDatabaseBackupLog>>(backupService.BeginListDatabaseBackupLogs, backupService.EndListDatabaseBackupLogs, serverName, databaseName, backupId, null);
            }
            catch (Exception e)
            {
                LogException("ListDatabaseBackupLogs", e);
            }
            return null;
        }


        public async Task<ObservableCollection<BackupContracts.Tasks.Task>> ListAllTasksAsync()
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                return await Task.Factory.FromAsync<ObservableCollection<BackupContracts.Tasks.Task>>(backupService.BeginListTasks, backupService.EndListTasks, null);
            }
            catch (Exception e)
            {
                LogException("ListTasks", e);
            }
            return null;
        }

        public async Task<bool> SaveTaskAsync(BackupContracts.Tasks.Task task)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                await Task.Factory.FromAsync<BackupContracts.Tasks.Task>(backupService.BeginUpsertTask, backupService.EndUpsertTask, task, null);
                return true;
            }
            catch (Exception e)
            {
                LogException("UpsertTask", e);
            }
            return false;
        }

        public async Task<bool> DeleteTaskAsync(BackupContracts.Tasks.Task task)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                await Task.Factory.FromAsync<string>(backupService.BeginDeleteTask, backupService.EndDeleteTask, task.Id, null);
                return true;
            }
            catch (Exception e)
            {
                LogException("DeleteTask", e);
            }
            return false;
        }

        public async Task<ObservableCollection<SqlServer>> ListAllServersAsync()
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                return await Task.Factory.FromAsync<ObservableCollection<SqlServer>>(backupService.BeginListSqlServers, backupService.EndListSqlServers, null);
            }
            catch (Exception e)
            {
                LogException("ListSqlServers", e);
            }
            return null;
        }

        public async Task<ObservableCollection<SqlDatabase>> ListAllSqlDatabases(string serverId)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                return await Task.Factory.FromAsync<string, ObservableCollection<SqlDatabase>>(backupService.BeginListSqlDatabases, backupService.EndListSqlDatabases, serverId, null);
            }
            catch (Exception e)
            {
                LogException("ListSqlDatabases", e);
            }
            return null;
        }

        public async Task<bool> SaveSqlServerAsync(SqlServer sqlServer)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                await Task.Factory.FromAsync<SqlServer>(backupService.BeginUpsertSqlServer, backupService.EndUpsertSqlServer, sqlServer, null);
                return true;
            }
            catch (Exception e)
            {
                LogException("UpsertSqlServer", e);
            }
            return false;
        }

        public async Task<bool> RemoveSqlServerAsync(SqlServer sqlServer)
        {
            try
            {
                var backupService = CreateBackupServiceClient();
                await Task.Factory.FromAsync<string>(backupService.BeginDeleteSqlServer, backupService.EndDeleteSqlServer, sqlServer.Id, null);
                return true;
            }
            catch (Exception e)
            {
                LogException("DeleteSqlServer", e);
            }
            return false;
        }
    }
}
